#ifndef _NA_TCP_CONNECTION_
#define _NA_TCP_CONNECTION_
#include <ctime>
#include <iostream>
#include <string>
#include <vector>
#include <boost/array.hpp>
#include <boost/thread/thread_time.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/asio.hpp>

#include "msg_base.h"
#include "read_buffer.h"

#define HEART_BEAT_MAX 6000 // 6 seconds

using boost::asio::ip::tcp;
namespace hoyosvr
{
	namespace net
	{
		class net_handler;
		
		typedef boost::shared_ptr< net_handler>   net_handler_pointer;
		enum gs_status  // game status
		{
			gs_null=0, // not ready
			gs_logining, // login
			gs_game    // in game progress
		};

		// tcp session class
		class tcp_session:
			public boost::enable_shared_from_this<tcp_session>
		{
			
		public:
			// tcp session shared pointer
			typedef boost::shared_ptr < tcp_session > ptr;
			tcp_session(size_t n = hoyosvr::msg::MAX_MSG_LENGTH); // default buffer size
			~tcp_session();

			// create a tcp session with specified buffer size
			static ptr	create(size_t n_buff_size);
			static void	destory(tcp_session* p);	

			// return current session socket
			tcp::socket& socket()		{	return socket_;	}

			// net id and session status
			inline	int	 get_net_id() const {return _net_id;}
			inline	void set_net_id(int net_id)  {_net_id=net_id;}
			inline	void set_session_status(int s) { _game_status = s;}
			inline	int get_session_status() const {return _game_status;}
			inline	int	 get_server_id() const {return _server_id;}
			inline	void set_server_id(int server)  {_server_id=server;}

			// start current tcp session
			void start(int net_id,net_handler_pointer handler_ptr);

			// client alive process
			bool is_alive(const boost::system_time& now_t);
			void keep_alive();

			// stop tcp session
			void stop();
			bool isSocketReady() { return _socket_is_ready;}

			// write message 
			void write(const char* data_ptr,int len,bool is_lock = true);
			void write_hoyo_msg( hoyosvr::msg::hoyo_msg& mj);
			void handle_write(boost::system::error_code /*error*/);
			
			// debug log information
			string getBufferInfo();

			// save player id
			int	 _player_id;

		private:
			
			// internal read or write message
			void write_impl(const char* data_ptr,int len);
			void handle_read(boost::system::error_code error,size_t bytes_transferred);	

			void post_read_null();
			void post_write_null();
			
			tcp::socket						socket_;
			net_handler_pointer				_net_handler_ptr;
			
			boost::mutex					m_write_mutex,m_read_mutex;
			char*							write_data_;
			size_t							write_buff_size;
			size_t							data_size_;
			read_buffer						_buff;

			int								_net_id;
			int								_server_id;
			int								_game_status;
			boost::system_time				_keep_alive;
				
			bool							write_in_progress_;
			bool							read_in_progress_;
			int								write_block_times;
			int								read_block_times;
			bool							_socket_is_ready;
            
		};
	}
}
#endif

